package com.gcmm.utils;

import cn.hutool.core.io.FileUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import javax.tools.*;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;


@Slf4j
public class TableUtils {
    private static String driverClassName = "com.mysql.cj.jdbc.Driver";
    @Getter
    @Setter
    private static String ip = "localhost";
    @Getter
    @Setter
    private static String port = "3306";
    @Getter
    @Setter
 private static String schema = "test";
    @Getter
    @Setter
    private static String url = "jdbc:mysql://"+ip+':'+port+"/"+ schema +"?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC";
    @Getter
    @Setter
    private static String username = "root";
    @Getter
    @Setter
    private static String password = "123456";

    public static String createTableByFile(MultipartFile inputFile) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException, SQLException {
        String projectPath = System.getProperty("user.dir");
        String tableTmpPath = projectPath + "\\target\\tableTmp\\";
        String classTmpPath = tableTmpPath + "class\\";
        String fileName = inputFile.getOriginalFilename();
log.info(" projectPath={} \n" +
        " tableTmpPath={}\n" +
        " classTmpPath={}\n" +
        " fileName = {}",projectPath,tableTmpPath,classTmpPath,fileName);
        //除去后缀
        String simpleFileName = fileName.substring(0, fileName.lastIndexOf("."));
        File localFile = new File(tableTmpPath + fileName);
        //创建文件夹
        localFile.mkdirs();
        inputFile.transferTo(localFile);
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        //指定编译文件的存放位置
        PrintStream printStream = new PrintStream(new FileOutputStream(tableTmpPath + "log.txt"));
        int result = compiler.run(null, null, printStream, "-d", classTmpPath, tableTmpPath + fileName);
printStream.close();
        //获取编译后的class文件路径
        String absoluteClassPath = FileUtil.loopFiles(classTmpPath).get(0).getAbsolutePath();
        //获取包名
        //6是class的长度+1
        String packagePath = absoluteClassPath.substring(absoluteClassPath.indexOf("class") + 6, absoluteClassPath.lastIndexOf("."));
        packagePath = packagePath.replace("\\", ".");
        ClassLoader classLoader = new URLClassLoader(new URL[]{new URL("file:///" + classTmpPath)});
        //获取类的对象
        Class<?> loadedClass = classLoader.loadClass(packagePath);
        //转化为更具体的子类
        Object table = loadedClass.getDeclaredConstructor().newInstance();
        String sql = createTableUtils(table, simpleFileName);
        //清空基础文件夹
        FileUtil.clean(tableTmpPath);
        return sql;
    }

    //获取类的属性名称
    private static String[] getClassFieldTypes(Object o) {
        Field[] fields = o.getClass().getDeclaredFields();
        String[] fieldTypes = new String[fields.length];
        for (int i = 0; i < fieldTypes.length; i++) {
            String originalType = fields[i].getType().toString();
            //取出类型的最后一个单词
            String type = originalType.substring(originalType.lastIndexOf(".") + 1);
            fieldTypes[i] = type;
        }
        return fieldTypes;
    }

    //获取类的属性类型
    private static String[] getClassFields(Object o) {
        Field[] fields = o.getClass().getDeclaredFields();

        String[] fieldNames = new String[fields.length];


        for (int i = 0; i < fieldNames.length; i++) {
            fieldNames[i] = getSqlName(fields[i].getName());
        }
        return fieldNames;
    }

    /**
     * 驼峰命名法转数据库命名
     *
     * @param name
     * @return
     */
    public static String getSqlName(String name) {
        String[] names = name.split("");
        String sqlname = "";
        for (int i = 0; i < names.length; i++) {
            if (names[i].equals(names[i].toUpperCase())) {
                sqlname = sqlname + "_" + names[i].toLowerCase();
            } else {
                sqlname = sqlname + names[i];
            }
        }
        return sqlname;
    }

    //自动生成sql语句
    public static String createTablesql(String tablename, Object obs) {
        //判断是否符合规范
        if (tablename.isEmpty() || obs == null) {
            return "参数不完整";
        }
        //获得类的属性名称
        String[] name = getClassFields(obs);
        String[] type = getClassFieldTypes(obs);
        String sql = "create table if not exists " + tablename + "(";
        //转换数据类型
        for (int i = 0; i < type.length; i++) {

            type[i] = switch (type[i]) {
                case "Long" -> "bigint";
                case "Integer" -> "int";
                case "LocalDateTime" -> "date";
                case "Double" -> "double";
                case "Float" -> "float";
                case "Boolean" -> "bit";
                default -> "varchar(255)";
            };

        }
        for (int i = 0; i < name.length - 1; i++) {
            sql = sql + name[i] + " " + type[i] + ",";
        }
        sql = sql + name[name.length - 1] + " " + type[name.length - 1] + ")";

        return sql;
    }

    public static String createTable(String sql, String tableName) throws ClassNotFoundException, SQLException {
        url = "jdbc:mysql://"+ip+':'+port+"/"+ schema +"?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC";

        log.info("url:{}",url);
      log.info("username:{}",username);
      log.info("password:{}",password);

        Connection conn = DriverManager.getConnection(url, username, password);
        Statement st = conn.createStatement();
        //4. 执行sql
        st.executeUpdate(sql);//创建表
        //5. 释放资源
        st.close();
        conn.close();
        return sql;
    }

    public static String createTableUtils(Object obs, String tableName) throws SQLException, ClassNotFoundException {

            String sql = createTablesql(tableName, obs);
            System.out.println(createTable(sql, tableName));

        return sql;
    }


}
